﻿// Bravura : A music composition and audio synthesis framework.
//
// Copyright © 2011 Paul Vanukoff (pvanukoff@gmail.com)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.

using System.Collections.Generic;
using Bravura.Core.PluginLib;

namespace Bravura.Core.SynthLib
{
	/// <summary>
	/// Internal implementation of IAudioBuffer.
	/// </summary>
	internal class AudioBuffer : IAudioBuffer
	{
		#region Private Fields

		private double _gain = 1.0;
		private double[] _data = new double[0];
		private List<AudioBuffer> _targets = new List<AudioBuffer>();

		#endregion

		#region Public Methods

		/// <summary>
		/// Connect this buffer to a downstream target buffer.
		/// </summary>
		public void Connect(AudioBuffer target)
		{
			_targets.Add(target);
		}

		/// <summary>
		/// Sets the gain applied when audio is written or mixed to this buffer.
		/// </summary>
		public void SetGain(double gain)
		{
			_gain = gain * gain;
		}

		/// <summary>
		/// Zero out this buffer.
		/// </summary>
		public void Zero(int count)
		{
			// resize up if needed
			if (count > _data.Length)
			{
				_data = new double[count];
			}

			// zero the buffer
			for (int i = 0; i < count; i++)
			{
				_data[i] = 0.0;
			}
		}

		/// <summary>
		/// Overwrite audio data from the supplied data array into this buffer.
		/// </summary>
		public void Write(double[] data, int count)
		{
			// resize up if needed
			if (count > _data.Length)
			{
				_data = new double[count];
			}

			// write the incoming data
			for (int i = 0; i < count; i++)
			{
				_data[i] = _gain * data[i];
			}

			// send the data to downstream buffers
			foreach (AudioBuffer target in _targets)
			{
				target.Mix(_data, count);
			}
		}

		/// <summary>
		/// Mix audio data from the supplied data array into this buffer.
		/// </summary>
		public void Mix(double[] data, int count)
		{
			// mix the incoming data
			for (int i = 0; i < count; i++)
			{
				_data[i] += _gain * data[i];
			}
		}

		/// <summary>
		/// Obtain the audio data from this buffer as a data array.
		/// </summary>
		public double[] Read(int count)
		{
			// return the buffer
			return _data;
		}

		#endregion
	}
}
